//Design a small memory system
//	Think about how it handles different debugging features like bounds checking and memory tracking?
//-----------------------------------------------------------------------------------------	
	//bounds checking: could be done by allocating bit more memory than needed. bytes before and after the requested memory block could then be 
	//marked with some special tokens.

	//tracking:
	//for memory tracking an own class can be used: MemoryTracker
	//contains a list with information about allocated memory blocks
	//could look like:
	typedef struct MemoryBlockInfo
	{
		// saves address from allocated memory 
		void*  ptr;
		// saves the number of bytes allocated
		size_t size;
		// saves line in which call to allocate was made
		unsigned int line;
		// saves filename in which call to allocate was made
		char* file;
		// flag to save the allocation method
		int allocFlag;
	} MemoryBlockInfo;

	//for tracking following function could be used:
	void TrackMemory(void* ptr, size_t size, unsigned int line, const char* file, int allocFlag); //allocFlag is used to track the different types of allocators.

//	How can they be enabled/disabled?
//-----------------------------------------------------------------------------------------	
	//As tracking is only done when memory is allocated or deallocated, a simple "#ifdef" around the call to the tracking function should be enough
#define MEMORY_TRACKING_ENABLED 1

	void* StackAllocator::StackAllocate(size_t size, unsigned int line, const char* file)
	{
		//do all the allocation stuff
		#ifdef MEMORY_TRACKING_ENABLED
		//track allocation
		#endif
	}
	

//	How can different allocators be used with the system? 	
//-----------------------------------------------------------------------------------------	
	//each allocator is implemented as a single class with functions to allocate and free memory.
	//using them is quite simple:
	//include header
	//instantiate allocator
	//allocate memory
	//free memory

	StackAllocator stackAlloc(100);
	LinearAllocator linearAlloc(50);	
	stackAlloc.StackAllocate(size_t size, unsigned int line, const char* file);
	stackAlloc.FreeMemory(void* toDelete, size_t size;)

//How are custom allocators supported?
//-----------------------------------------------------------------------------------------	
	//Isn't it almost the same question as the upper one?
	//You can easily implement and use custom allocators. The only thing you have to consider is tracking. 
	//If you want to track the allocations a call to TrackMemory function of the MemoryTracker class is necessary

//	How are instances of structs/classes allocated and instantiated?
//-----------------------------------------------------------------------------------------	
	//-when using a stack allocator for example, allocation would look like following
	TestClass* testclass = (TestClass*)stackAlloc.StackAllocate(sizeof(TestClass), __LINE__, __FILE__);
	//would work the same way with any other allocator

//	How are raw memory allocations handled?
//-----------------------------------------------------------------------------------------	
	void* rawMemory = stackAlloc.StackAllocate(10, __LINE__, __FILE__);
	//with providing the size of needed memory instead of datatype/class/whatever 
	

//	How does the system handle different alignments?
//-----------------------------------------------------------------------------------------	
	//one way would be to pass the "alignment value" to the allocate function
	void* Allocate(size_t size, int line, char* file, int alignment);
	//if the whole application should use same alignment maybe with a global state
	#define ALIGNMENT 32
	//alignment handling itself will we be done in the allocate method of the different allocators

//How is the system integrated into the C++ ecosystem?
//-----------------------------------------------------------------------------------------	

//Does the code still use new & delete?
//-----------------------------------------------------------------------------------------	
	//Depends. When initializing an allocator, the constructor is used to create the memory pool with the size needed. I'm using malloc therefore
	StackAllocator stackAlloc(100);  //create a stack allocator with a size of 100 bytes

	//ctor
	StackAllocator::StackAllocator(size_t size)
		: poolSize(size), totalSize(0)
	{
		startPointer = malloc(poolSize);	//startPointer is pointing at the beginning of the memory pool
		freePointer = startPointer;			//freePointer is moved with every allocation
	}

	//when allocating memory later, each allocator has its own allocate method which gives back free memory from the pool.

	//its also possible allocate memory without any allocator
	int* a = new int;
	int* b = new(__LINE__,__FILE__);	

//	What does doing an allocation look like (in code)?
//-----------------------------------------------------------------------------------------	
	//as already written before, could be:
	TestClass* testclass = (TestClass*)stackAlloc.StackAllocate(sizeof(TestClass), __LINE__, __FILE__);



	
//	Like exercise 1:
//Show how allocations are made with the system. Show how different allocators can be used.
//-----------------------------------------------------------------------------------------	
	//There should be enough examples in the previous questions about this.

//	Describe the architecture
//-----------------------------------------------------------------------------------------	
	//Class Allocator
	//allocators are implemented as single classes. there are two important functions which are used for allocating and deallocating memory.
	//constructor is used to allocate a memory pool so you don't have any dynamic allocations later

	//Class MemoryTracker
	//stores information about allocated memory blocks.
	//is responsible for tracking the allocations




//	Describe the pros and cons you can see with your approach
//-----------------------------------------------------------------------------------------	
	//+	It's easy to add new allocators
	//+ After the memory pools for the allocators are created, you have no dynamic allocations.
	//+
	//- Usage of some static flags to determine which allocator is used when tracking allocations.
	//- I don't like the way of tracking the allocations
	//-